﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Text;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using RabbitMQ.Client.MessagePatterns;

namespace ATPlatforms.RabbitSkin.Serializers
{
    public class AsyncSimpleRpcClient: SimpleRpcClient, IDisposable 
    {
             //Callback for message received
        public delegate void OnReply(BasicDeliverEventArgs basicDeliverEventArgs);
        public event OnReply OnReplyEvent;



        public AsyncSimpleRpcClient(IModel model, string queueName, OnReply replyCallback) : base(model, queueName)
        {
            
            OnReplyEvent += replyCallback;
         
        }


        private void EnsureRunning()
        {
            if (!Running)
            {
                Running = true;
                RetrieveReplyDelgate d = new RetrieveReplyDelgate(RetrieveAsyncReply);
                d.BeginInvoke(null, null);
            }
        }

        public string AsyncCall(byte[] body)
        {
            return AsyncCall(null, body);
        }

        public string AsyncCall(IBasicProperties requestProperties, byte[] body)
        {
            EnsureSubscription();
            EnsureRunning();
            if (requestProperties == null)
            {
                requestProperties = m_model.CreateBasicProperties();
            }
            requestProperties.CorrelationId = Guid.NewGuid().ToString();
            requestProperties.ReplyTo = m_subscription.QueueName;
            Cast(requestProperties, body);
            return requestProperties.CorrelationId;
        }

        private delegate void RetrieveReplyDelgate() ;

        private bool Running;
        protected virtual void RetrieveAsyncReply()
        {
            while (Running)
            {
                BasicDeliverEventArgs reply = m_subscription.Next();
                if (reply == null)
                {
                    OnDisconnected();
                    return;
                }
                OnReplyEvent.Invoke(reply);
                m_subscription.Ack(reply);

            }
        }

        public void Dispose()
        {
            Running = false;
            Close();
        }

    }
}
